package algorithms;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;

import fileloaders.mallet.MalletTopicsProbs;

import puppy.eval.logloaders.FeaturesLoader;
import puppy.graph.AgeAggregator;
import puppy.graph.CreateGraphDirected;
import puppy.graph.CreateLM;
import puppy.graph.CreateUnigrams;
import puppy.graph.DeliciousEdgeSimple;
import util.evaluation.QueryTag;
import util.hashing.Sorting;
import util.math.LogProb;
import algorithms.models.QueryTagsModel;

public class TopicFeatures {

	public CreateGraphDirected graph = null;
	CreateLM lm = null;
	double query_total = 0;

	int topic_limit = 20;
	AgeAggregator agg = null;
	Hashtable<String, ArrayList<String>> queries_todo = null;
	QueryTagsModel querytags = null;
	CreateUnigrams unigrams = null;
	private int query_threshold_freq;

	public Hashtable<String, Hashtable<Short, Float>> w_topics = new Hashtable<String, Hashtable<Short, Float>>();

	public Hashtable<String, Hashtable<Short, Float>> topics_w = new Hashtable<String, Hashtable<Short, Float>>();

	public Hashtable<String, Hashtable<Short, Float>> topics_docs = new Hashtable<String, Hashtable<Short, Float>>();
	public Hashtable<String, Float> z_probs = new Hashtable<String, Float>();

	public void initTopics(String w_p, String p_w, String d_p, String z_path) {

		if (w_p != null && d_p != null) {
			MalletTopicsProbs.loadTopicGivenDoc(d_p, topics_docs);
			MalletTopicsProbs.loadTopicGivenWord(w_p, w_topics);
			MalletTopicsProbs.loadTopicGivenWord(p_w, topics_w);
		}

		MalletTopicsProbs.loadTopicProbs(z_path, z_probs);

	}

	public TopicFeatures(String graph, String w_p, String p_w, String d_p,
			String z_path, String query_tags, String features,
			HashSet<String> ages) {

		queries_todo = FeaturesLoader.loadQueryTagsFeatures(features);
		initTopics(w_p, p_w, d_p, z_path);
		this.agg = new AgeAggregator(ages);
		unigrams = new CreateUnigrams(agg, graph);
		HashSet<String> queries = init_queries_to_eval(queries_todo);
		querytags = new QueryTagsModel(query_tags, queries);

	}

	private HashSet<String> init_queries_to_eval(
			Hashtable<String, ArrayList<String>> queries_todo2) {
		// TODO Auto-generated method stub
		HashSet<String> queries = new HashSet<String>();

		Enumeration<String> keys = queries_todo2.keys();
		while (keys.hasMoreElements()) {

			String query = keys.nextElement();
			queries.add(query);
		}
		return queries;
	}

	public void initLM(String path) {
		if (path == null)
			return;

		lm = new CreateLM();
		lm.initLM(path);
	}

	public void print_topic_features_features() {

		Enumeration<String> queries = queries_todo.keys();
		while (queries.hasMoreElements()) {
			String query = queries.nextElement();
			ArrayList<String> sugg = queries_todo.get(query);
			ArrayList<QueryTag> query_model = querytags.getQueries().get(query);
			Hashtable<String, Float> query_ratios = calculateQueryRatios(query_model);
			for (int i = 0; i < sugg.size(); i++) {

				String tag = sugg.get(i);

				// join probability
				double lm_value = calcualteLM_topics(query_ratios, tag);

				System.out
						.println(query + "\t" + tag + "\ttopics\t" + lm_value);
				// google distance
				double lm_value_n = calcualteTopTopics(query_ratios, tag);

				System.out.println(query + "\t" + tag + "\ttopics_top\t"
						+ lm_value_n);

			}

		}
	}

	private double calcualteLM_topics(Hashtable<String, Float> query_ratios,
			String tag) {
		// TODO Auto-generated method stub

		Enumeration<String> keys = query_ratios.keys();

		double similarity = 0;
		while (keys.hasMoreElements()) {

			String key = keys.nextElement();
			double ratio = query_ratios.get(key);

			// loop for all topics of qi:
			double score = 0.0;
			double sum_topics = 0.0;
			if (w_topics.containsKey(key)) {
			
				Hashtable<Short, Float> temp = w_topics.get(key);
				Hashtable<Short, Float> temp2 = getTopTopics(temp, topic_limit);
				Enumeration<Short> topics = temp2.keys();

				//Enumeration<Short> topics = temp.keys();
				while (topics.hasMoreElements()) {
					

					Short topic = topics.nextElement();
					
					// we need p(qi|z)
					double q_z = temp2.get(topic);
				
					// and p(z|ti)
					double z_t = 0.0;
					if (topics_w.containsKey(tag)
							&& topics_w.get(tag).containsKey(topic)) {
						z_t = topics_w.get(tag).get(topic);
					}
					//System.out.println(topic +"\t"+ q_z+ "\t"+ z_t + "\t"+  q_z * z_t+ "\t"+ sum_topics);

					double prob = q_z * z_t;

					sum_topics = sum_topics + prob;

				}// end iterator of z topics of qi
				//System.out.println("Aggregata " + sum_topics);
			}// end if w_topics

			//sum topics to log space
			
			
			similarity += sum_topics*ratio;
			
		
		//	System.out.println(score + "\t"+ similarity  );
		}

		return similarity;

	}

	private Hashtable<Short, Float> getTopTopics(Hashtable<Short, Float> z,
			int n) {

		Iterator<Short> temp = Sorting.getTopN_ThresholdTopics(z, false, n);
		Hashtable<Short, Float> sorted = new Hashtable<Short, Float>();

		while (temp.hasNext()) {

			Short key = temp.next();

			sorted.put(key, z.get(key));
		}

		temp = null;
		z = null;
		return sorted;
	}

	private double calcualteTopTopics(Hashtable<String, Float> query_ratios,
			String tag) {
		// TODO Auto-generated method stub

		Enumeration<String> keys = query_ratios.keys();

		double similarity = 0;
		while (keys.hasMoreElements()) {

			String key = keys.nextElement();
			float ratio = query_ratios.get(key);

			// loop for all topics of qi:
			double score = 0.0;
			double sum_topics = 0.0;
			if (w_topics.containsKey(key)) {
				Hashtable<Short, Float> temp = w_topics.get(key);

				Hashtable<Short, Float> temp2 = getTopTopics(temp, topic_limit);
				Enumeration<Short> topics = temp2.keys();
				while (topics.hasMoreElements()) {

					Short topic = topics.nextElement();
					// we need p(qi|z)
					double q_z = temp2.get(topic);

					// and p(z|ti)
					double z_t = 0.0;
					if (topics_w.containsKey(tag)
							&& topics_w.get(tag).containsKey(topic)) {
						z_t = topics_w.get(tag).get(topic);
					}

					double prob = q_z * z_t;

					sum_topics = sum_topics + prob;

				}// end iterator of z topics of qi

			}// end if w_topics

			score = score + ratio * sum_topics;

		}

		return similarity;

	}

	public Hashtable<String, Float> calculateQueryRatios(ArrayList<QueryTag> q) {

		Hashtable<String, Float> qq = new Hashtable<String, Float>();
		double total = 0;
		for (int i = 0; i < q.size(); i++) {
			QueryTag element = q.get(i);
			total = total + element.freq;
		}
		for (int i = 0; i < q.size(); i++) {
			QueryTag element = q.get(i);
			total = total + element.freq;

			if (element.freq >= query_threshold_freq) {
				// if(tag.equals("characterized")){System.out.println("aqui si estuvo characterizeds "
				// );}
				qq.put(element.tag, (float) ((float) element.freq / total));
			}

		}

		// System.out.println( q+"\t"+ qq);
		return qq;
	}

	public static void main(String argvs[]) {

		String path = "../data/graph/last/delcious_graph_merged_enriched_inline_kids.txt";
		// static String path = "../data/graph/last/samplet.txt";

		String query_tags = "../data/query_tags/query_and_tags_sorted_aol.txt";
		String output_path = "/home/sergio/projects/learning_rank/query_suggestions/dmoz/features/rw_ranks.txt";

		String topics_docs = "../data/topics/kids_simple30/100_output_doc_topics.txt";
		String topics_words = "../data/topics/kids_simple30/topic_given_word_normalized.txt";
		String words_topics = "../data/topics/kids_simple30/word_given_topic_normalized.txt";
		String query_topics_path = "../data/topics/kids_simple30/query/100_output_doc_topics_enriched.txt";
		String topics_probabilities = "../data/topics/kids_simple30/topics_probabilities.txt";

		String features = "/home/sergio/projects/learning_rank/query_suggestions/models/big_feature_file_clean.txt";

		String age = "teens-mteens";

		HashSet<String> ages = new HashSet<String>();
		ages.add(age);
		ages.add("kids-teen-mteens");
		ages.add("kids-teens");

		// String w_p, String p_w,String d_p, String z_path
		TopicFeatures sim = new TopicFeatures(path, words_topics, topics_words,
				topics_docs, topics_probabilities, query_tags, features, ages);
		sim.print_topic_features_features();
	}

}
